package puzzle.akari.solver;

import java.util.ArrayList;
import java.util.List;

import puzzle.akari.data.AkariBoard;
import puzzle.akari.data.BlockNumber;
import puzzle.common.data.HatanException;
import puzzle.common.point.Direction;
import puzzle.common.point.Pnt;
import puzzle.common.solver.BoardRule;

class PossibilityToBeLitRule extends AkariCellRule implements BoardRule<AkariBoard> {

	@Override
	protected boolean apply(AkariBoard b, int x, int y) throws HatanException {
		if (BlockNumber.isBlock(b.getBlockNumber(x, y)) || b.isLit(x, y)) {
			return false;
		}

		// this is a dark cell, whether forbidden or not

		List<Pnt> possiblePoints = new ArrayList<Pnt>();
		for (Direction d : Direction.CLOCKWISE4) {
			findPossibleLightPoints(b, x, y, d, possiblePoints, 2);
			if (possiblePoints.size() >= 2) {
				break;
			}
		}

		if (possiblePoints.size() == 0) {
			return b.setLightPut(x, y);
		}

		if (possiblePoints.size() == 1 && b.isLightForbidden(x, y)) {
			return b.setLightPut(possiblePoints.get(0));
		}
		
		return false;
	}

	private void findPossibleLightPoints(AkariBoard b, int x, int y, Direction d,
			List<Pnt> possiblePoints, int maxPossibilities) {
		while (true) {
			x += d.v.dx;
			y += d.v.dy;
			if (BlockNumber.isBlock(b.getBlockNumber(x, y)) || b.isLightPut(x, y)) {
				return;
			}
			if (!b.isLightForbidden(x, y)) {
				possiblePoints.add(new Pnt(x, y));
				if (possiblePoints.size() >= maxPossibilities) {
					return;
				}
			}
		}
	}

}
